package com.qf.ability.auth.controller;

import com.alibaba.fastjson.JSON;
import com.qf.ability.auth.service.SysPowerService;
import com.qf.common.core.base.R;
import com.qf.common.core.base.RetUtils;
import com.qf.common.core.utils.UserInfo;
import com.qf.data.entity.auth.SysPower;
import com.qf.data.entity.auth.dto.SysPowerDto;
import com.qf.data.entity.auth.vo.SysPowerTreeVo;
import com.qf.data.entity.auth.vo.SysPowerVo;
import com.qf.data.entity.auth.vo.SysUserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotBlank;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/sys/power")
@Slf4j
public class SysPowerController {

    @Autowired
    private SysPowerService sysPowerService;

    @PreAuthorize("hasAuthority('/SysPowerManager')")
    @RequestMapping("/queryAll")
    public R queryAll(){

        List<SysPowerVo> sysPowers = sysPowerService.queryAll();
        return RetUtils.createSucc(sysPowers);
    }

    /**
     * 修改角色对应的权限列表
     * @return
     */
    @RequestMapping("/updatePowerByRole")
    public R updatePowerByRole(Long roid, String poids){
        //获得权限集合
        List<Long> poidList = JSON.parseArray(poids, Long.class);
        sysPowerService.updatePowerByRole(roid, poidList);
        return RetUtils.createSucc(true);
    }

    /**
     * 根据用户id查询对应的菜单列表
     * @return
     */
    @RequestMapping("/queryPowersByUid")
    public R queryPowersByUid(){
        //获取当前的登录
        SysUserVo sysUserVo = UserInfo.getUser();
        //查询当前用户下的所有权限
        List<SysPower> sysPowers = sysPowerService.queryPowersByUid(sysUserVo.getUId());
        return RetUtils.createSucc(sysPowers);
    }

    /**
     * 根据角色id查询对应的权限列表
     * @return
     */
    @RequestMapping("/queryPowersByRoid")
    public R queryPowersByRoid(@Validated @NotBlank(message = "角色id不能为空") Long roid){
        List<SysPowerDto> sysPowerDtos = sysPowerService.queryPowersByRoid(roid);
        log.debug("[query-role-powers] - 查询指定角色的权限列表 - 角色id:{} - {}", roid, sysPowerDtos);
        //List<SysPowerDto> -> List<SysPowerTreeVo>
        /*
        1 null 菜单1
        2  1   菜单2
        3  1   菜单3
        4  3   菜单4
        5 null 菜单5
        ...

        ----> 转换
        1 null 菜单1 children[ {2,1,菜单2}, {3,1,菜单3, children[{4,3,菜单4}]} ]

        rootTreeVos -> List[菜单1，菜单5]

        keyMaps -> Map{
          1: List[菜单2,菜单3],
          3: List[菜单4]
          ....
        }
         */

        //查询所有的顶级菜单
        List<SysPowerTreeVo> rootTreeVos = sysPowerDtos
                .stream()
                .filter(sysPowerDto -> sysPowerDto.getPrPid() == null)
                .map(sysPowerDto -> new SysPowerTreeVo()
                        .setId(sysPowerDto.getPrId())
                        .setPrName(sysPowerDto.getPrName())
                        .setStatus(sysPowerDto.getStatus())
                        .setChecked(sysPowerDto.isChecked()))
                .collect(Collectors.toList());

        //Map{key:父权限id， value:List[SysPowerTreeVo]}
        //将集合转换成Map集合，方法后续查询
        Map<Long, List<SysPowerTreeVo>> keyMaps = sysPowerDtos
                .stream()
                .filter(sysPowerDto -> sysPowerDto.getPrPid() != null)
                .collect(Collectors.toMap(
                        //设置转换后Map的key
                        sysPowerDto -> sysPowerDto.getPrPid(),
                        //设置转换后Map的value
                        sysPowerDto -> {
                            List<SysPowerTreeVo> list = new ArrayList<>();
                            list.add(new SysPowerTreeVo()
                                    .setId(sysPowerDto.getPrId())
                                    .setPrName(sysPowerDto.getPrName())
                                    .setStatus(sysPowerDto.getStatus())
                                    .setChecked(sysPowerDto.isChecked()));
                            return list;
                        },
                        //解决当key相同时，value的处理方式
                        (o, o2) -> {
                            o.addAll(o2);
                            return o;
                        }
                ));

        rootTreeVos = sysPowerList2Trees(rootTreeVos, keyMaps);

        return RetUtils.createSucc(rootTreeVos);
    }

    /**
     * 递归方法 - 将权限列表转换成权限树结构
     */
    public List<SysPowerTreeVo> sysPowerList2Trees(List<SysPowerTreeVo> parentTreeVos, Map<Long, List<SysPowerTreeVo>> keyMaps){

        //递归的结束方法
        if (parentTreeVos == null) return null;

        //循环所有根节点
        for (SysPowerTreeVo parentTreeVo : parentTreeVos) {
            //根节点的id
            Long id = parentTreeVo.getId();
            //获取当前节点下的所有子节点
            List<SysPowerTreeVo> sonTreeVos = keyMaps.get(id);
            //设置根节点的子节点集合
            parentTreeVo.setChildren(sonTreeVos);

            //递归调用
            sysPowerList2Trees(sonTreeVos, keyMaps);
        }

        return parentTreeVos;
    }
}
